/**
 * Copyright (c) 2018-2023, NXOS Development Team
 * SPDX-License-Identifier: Apache-2.0
 * 
 * Contains: message queue test 
 * 
 * Change Logs:
 * Date           Author            Notes
 * 2023-09-07     JasonHu           Init
 */

#include <test/utest.h>
#include <base/msgqueue.h>
#include <base/string.h>
#include <base/memory.h>

#ifdef CONFIG_NX_UTEST_MSG_QUEUE

NX_TEST(NX_MsgQueueCreate)
{
    NX_MsgQueue *mq;
    
    mq = NX_MsgQueueCreate(0, 64);
    NX_ASSERT_EQ(mq, NX_NULL);

    mq = NX_MsgQueueCreate(256, 0);
    NX_ASSERT_EQ(mq, NX_NULL);

    mq = NX_MsgQueueCreate(256, 64);
    NX_ASSERT_NE(mq, NX_NULL);
    
    NX_ASSERT_EQ(NX_MegQueueDestroy(mq), NX_EOK);
}

NX_TEST(NX_MsgQueueSend)
{
    NX_MsgQueue *mq;
    NX_MsgBuf mbuf;
    char buf[64];
    
    mq = NX_MsgQueueCreate(256, 64);
    NX_ASSERT_NE(mq, NX_NULL);

    NX_ASSERT_NE(NX_MsgQueueSend(NX_NULL, NX_NULL), NX_EOK);
    NX_ASSERT_NE(NX_MsgQueueSend(mq, NX_NULL), NX_EOK);

    mbuf.payload = NX_NULL;
    mbuf.len = 0;
    NX_ASSERT_NE(NX_MsgQueueSend(mq, &mbuf), NX_EOK);

#define TEST_MSG_STR "hello, world!"
    mbuf.payload = TEST_MSG_STR;
    mbuf.len = 0;
    NX_ASSERT_NE(NX_MsgQueueSend(mq, &mbuf), NX_EOK);

    mbuf.payload = NX_NULL;
    mbuf.len = 100;
    NX_ASSERT_NE(NX_MsgQueueSend(mq, &mbuf), NX_EOK);
    
    mbuf.payload = TEST_MSG_STR;
    mbuf.len = sizeof(TEST_MSG_STR);
    NX_ASSERT_EQ(NX_MsgQueueSend(mq, &mbuf), NX_EOK);
    
    mbuf.payload = TEST_MSG_STR;
    mbuf.len = sizeof(TEST_MSG_STR);
    NX_ASSERT_EQ(NX_MsgQueueSend(mq, &mbuf), NX_EOK);

    NX_MemZero(buf, 64);
    mbuf.payload = buf;
    mbuf.len = 64;
    NX_ASSERT_EQ(NX_MsgQueueRecv(mq, &mbuf), NX_EOK);
    NX_ASSERT_EQ(NX_StrCmp(buf, TEST_MSG_STR), 0);
    NX_ASSERT_EQ(mbuf.len, sizeof(TEST_MSG_STR));
    NX_MemZero(buf, 64);
    NX_ASSERT_EQ(NX_MsgQueueRecv(mq, &mbuf), NX_EOK);
    NX_ASSERT_EQ(NX_StrCmp(buf, TEST_MSG_STR), 0);
    NX_ASSERT_EQ(mbuf.len, sizeof(TEST_MSG_STR));

    NX_ASSERT_EQ(NX_MegQueueDestroy(mq), NX_EOK);
}

NX_TEST(NX_MsgQueueRecv)
{
    NX_MsgQueue *mq;
    NX_MsgBuf mbuf;
    char buf[64];
    
    mq = NX_MsgQueueCreate(256, 64);
    NX_ASSERT_NE(mq, NX_NULL);

    NX_ASSERT_NE(NX_MsgQueueRecv(NX_NULL, NX_NULL), NX_EOK);
    NX_ASSERT_NE(NX_MsgQueueRecv(mq, NX_NULL), NX_EOK);

    mbuf.payload = NX_NULL;
    mbuf.len = 0;
    NX_ASSERT_NE(NX_MsgQueueRecv(mq, &mbuf), NX_EOK);

#define TEST_MSG_STR "hello, world!"
    mbuf.payload = TEST_MSG_STR;
    mbuf.len = 0;
    NX_ASSERT_NE(NX_MsgQueueRecv(mq, &mbuf), NX_EOK);

    mbuf.payload = TEST_MSG_STR;
    mbuf.len = sizeof(TEST_MSG_STR);
    NX_ASSERT_EQ(NX_MsgQueueSend(mq, &mbuf), NX_EOK);
    
    mbuf.payload = TEST_MSG_STR;
    mbuf.len = sizeof(TEST_MSG_STR);
    NX_ASSERT_EQ(NX_MsgQueueSend(mq, &mbuf), NX_EOK);

    NX_MemZero(buf, 64);
    mbuf.payload = buf;
    mbuf.len = 64;
    NX_ASSERT_EQ(NX_MsgQueueRecv(mq, &mbuf), NX_EOK);
    NX_ASSERT_EQ(NX_StrCmp(buf, TEST_MSG_STR), 0);
    NX_ASSERT_EQ(mbuf.len, sizeof(TEST_MSG_STR));
    NX_MemZero(buf, 64);
    NX_ASSERT_EQ(NX_MsgQueueRecv(mq, &mbuf), NX_EOK);
    NX_ASSERT_EQ(NX_StrCmp(buf, TEST_MSG_STR), 0);
    NX_ASSERT_EQ(mbuf.len, sizeof(TEST_MSG_STR));

    NX_ASSERT_EQ(NX_MegQueueDestroy(mq), NX_EOK);
}

NX_TEST(NX_MsgQueueTrySend)
{
    NX_MsgQueue *mq;
    NX_MsgBuf mbuf;
    char buf[64];
    
    mq = NX_MsgQueueCreate(256, 3);
    NX_ASSERT_NE(mq, NX_NULL);

    NX_ASSERT_NE(NX_MsgQueueTrySend(NX_NULL, NX_NULL), NX_EOK);
    NX_ASSERT_NE(NX_MsgQueueTrySend(mq, NX_NULL), NX_EOK);

    mbuf.payload = NX_NULL;
    mbuf.len = 0;
    NX_ASSERT_NE(NX_MsgQueueTrySend(mq, &mbuf), NX_EOK);

#define TEST_MSG_STR "hello, world!"
    mbuf.payload = TEST_MSG_STR;
    mbuf.len = 0;
    NX_ASSERT_NE(NX_MsgQueueTrySend(mq, &mbuf), NX_EOK);

    mbuf.payload = NX_NULL;
    mbuf.len = 100;
    NX_ASSERT_NE(NX_MsgQueueTrySend(mq, &mbuf), NX_EOK);
    
    /* send ok */
    NX_ASSERT_EQ(NX_MsgQueueEmpty(mq), NX_True);
    mbuf.payload = TEST_MSG_STR;
    mbuf.len = sizeof(TEST_MSG_STR);
    NX_ASSERT_EQ(NX_MsgQueueTrySend(mq, &mbuf), NX_EOK);
    
    mbuf.payload = TEST_MSG_STR;
    mbuf.len = sizeof(TEST_MSG_STR);
    NX_ASSERT_EQ(NX_MsgQueueTrySend(mq, &mbuf), NX_EOK);

    mbuf.payload = TEST_MSG_STR;
    mbuf.len = sizeof(TEST_MSG_STR);
    NX_ASSERT_EQ(NX_MsgQueueTrySend(mq, &mbuf), NX_EOK);

    mbuf.payload = TEST_MSG_STR;
    mbuf.len = sizeof(TEST_MSG_STR);
    NX_ASSERT_NE(NX_MsgQueueTrySend(mq, &mbuf), NX_EOK);

    NX_ASSERT_EQ(NX_MsgQueueFull(mq), NX_True);

    NX_MemZero(buf, 64);
    mbuf.payload = buf;
    mbuf.len = 64;
    NX_ASSERT_EQ(NX_MsgQueueRecv(mq, &mbuf), NX_EOK);
    NX_ASSERT_EQ(NX_StrCmp(buf, TEST_MSG_STR), 0);
    NX_ASSERT_EQ(mbuf.len, sizeof(TEST_MSG_STR));
    NX_MemZero(buf, 64);
    NX_ASSERT_EQ(NX_MsgQueueRecv(mq, &mbuf), NX_EOK);
    NX_ASSERT_EQ(NX_StrCmp(buf, TEST_MSG_STR), 0);
    NX_ASSERT_EQ(mbuf.len, sizeof(TEST_MSG_STR));
    NX_MemZero(buf, 64);
    NX_ASSERT_EQ(NX_MsgQueueRecv(mq, &mbuf), NX_EOK);
    NX_ASSERT_EQ(NX_StrCmp(buf, TEST_MSG_STR), 0);
    NX_ASSERT_EQ(mbuf.len, sizeof(TEST_MSG_STR));
    NX_ASSERT_EQ(NX_MegQueueDestroy(mq), NX_EOK);
}

NX_TEST(NX_MsgQueueTryRecv)
{
    NX_MsgQueue *mq;
    NX_MsgBuf mbuf;
    char buf[64];
    
    mq = NX_MsgQueueCreate(256, 3);
    NX_ASSERT_NE(mq, NX_NULL);

    NX_ASSERT_NE(NX_MsgQueueTryRecv(NX_NULL, NX_NULL), NX_EOK);
    NX_ASSERT_NE(NX_MsgQueueTryRecv(mq, NX_NULL), NX_EOK);

    mbuf.payload = NX_NULL;
    mbuf.len = 0;
    NX_ASSERT_NE(NX_MsgQueueTryRecv(mq, &mbuf), NX_EOK);

#define TEST_MSG_STR "hello, world!"
    mbuf.payload = TEST_MSG_STR;
    mbuf.len = 0;
    NX_ASSERT_NE(NX_MsgQueueTryRecv(mq, &mbuf), NX_EOK);

    mbuf.payload = TEST_MSG_STR;
    mbuf.len = sizeof(TEST_MSG_STR);
    NX_ASSERT_EQ(NX_MsgQueueSend(mq, &mbuf), NX_EOK);
    
    mbuf.payload = TEST_MSG_STR;
    mbuf.len = sizeof(TEST_MSG_STR);
    NX_ASSERT_EQ(NX_MsgQueueSend(mq, &mbuf), NX_EOK);

    NX_MemZero(buf, 64);
    mbuf.payload = buf;
    mbuf.len = 64;
    NX_ASSERT_EQ(NX_MsgQueueTryRecv(mq, &mbuf), NX_EOK);
    NX_ASSERT_EQ(NX_StrCmp(buf, TEST_MSG_STR), 0);
    NX_ASSERT_EQ(mbuf.len, sizeof(TEST_MSG_STR));
    NX_MemZero(buf, 64);
    NX_ASSERT_EQ(NX_MsgQueueTryRecv(mq, &mbuf), NX_EOK);
    NX_ASSERT_EQ(NX_StrCmp(buf, TEST_MSG_STR), 0);
    NX_ASSERT_EQ(mbuf.len, sizeof(TEST_MSG_STR));
    
    NX_ASSERT_NE(NX_MsgQueueTryRecv(mq, &mbuf), NX_EOK);
    
    NX_ASSERT_EQ(NX_MegQueueDestroy(mq), NX_EOK);
}

NX_TEST_TABLE(NX_MsgQueue)
{
    NX_TEST_UNIT(NX_MsgQueueCreate),
    NX_TEST_UNIT(NX_MsgQueueSend),
    NX_TEST_UNIT(NX_MsgQueueRecv),
    NX_TEST_UNIT(NX_MsgQueueTrySend),
    NX_TEST_UNIT(NX_MsgQueueTryRecv),
};

NX_TEST_CASE(NX_MsgQueue);

#endif
